package com.lab.webSocket.webSocket;

/**
 * Created by xu_jiaHui on 2017/8/26.
 */


import com.fasterxml.jackson.databind.ObjectMapper;
import com.lab.webSocket.dto.UserInfoDto;
import com.lab.webSocket.service.AddUserService;
import com.lab.webSocket.service.ChatService;
import com.lab.webSocket.service.FriendListService;
import com.lab.webSocket.webSocket.dto.TextChatResultDto;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;

@Service
public class WebSocketEndPoint extends AbstractWebSocketHandler {


    /**
     * @Description: 用户账号 和 Session
     * @author xu_jiaHui
     * @date 2017/9/7 19:25
     */
    private static final Map<String, WebSocketSession> userSessionMap;


    static {
        userSessionMap = new HashMap<String, WebSocketSession>();
    }

    @Resource
    private ChatService chatService;

    @Resource
    private FriendListService friendListService;

    @Resource
    private AddUserService addUserService;


    /**
     * @Description: 成功建立连接之后调用
     * @author xu_jiaHui
     * @date 2017/8/31 18:07
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        TextChatResultDto dto = new TextChatResultDto("connect", "连接成功");
        session.sendMessage(formatMsg(dto));
    }

    /**
     * @Description: 对接前端onMessage方法
     * @author xu_jiaHui
     * @date 2017/8/28 15:55
     */
    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        String jsonMsg = message.getPayload().toString();
        ObjectMapper om = new ObjectMapper();
        try {
            TextChatResultDto jsonDto = om.readValue(jsonMsg, TextChatResultDto.class);
            if (jsonDto.getType().equals("login"))
                bindUserSession(jsonDto, session);
            else if (jsonDto.getType().equals("group"))
                sendMsgToGroup(jsonDto);
            else if (jsonDto.getType().equals("p2p"))
                sendMsgToUser(jsonDto, session);
            else if (jsonDto.getType().equals("heartBeat"))
                session.sendMessage(message);
            else if (jsonDto.getType().equals("addFriend") ||
                    jsonDto.getType().equals("addFriendResult"))
                sendMsgToUser(jsonDto, session);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * @Description: 获取好友列表(显示在线)
     * @author xu_jiaHui
     * @date 2017/9/8 18:30
     */
    public List<UserInfoDto> getOnlineList(String userAccount) {
        try {
            Set<String> clientIds = userSessionMap.keySet();
            List<UserInfoDto> userInfoDtos = friendListService.getFriendListByUserAccount(userAccount);
            for (String user : clientIds) {
                for (UserInfoDto dtos : userInfoDtos) {
                    if (user.equals(dtos.getUserAccount())) {
                        dtos.setIsOnline(1);
                        break;
                    }
                }
            }
            return userInfoDtos;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("获取在线列表失败");
        }
        return null;

    }

    /**
     * @Description: 私聊
     * @author xu_jiaHui
     * @date 2017/9/4 16:52
     */
    private void sendMsgToUser(TextChatResultDto jsonDto, WebSocketSession session) {
        try {
            session.sendMessage(formatMsg(jsonDto));
            String userTarget = jsonDto.getUserTarget();
            WebSocketSession client = userSessionMap.get(userTarget);
            if (client != null && client.isOpen()) {
                client.sendMessage(formatMsg(jsonDto));
            } else {
                chatService.sendMessage(jsonDto);
                System.out.println("对方用户已离线");
            }
            if (jsonDto.getType().equals("addFriendResult")) {
                try {
                    if (jsonDto.getContent().equals("1"))
                        addUserService.addFriendByUserAccount(jsonDto.getUserAccount(), jsonDto.getUserTarget());
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("添加好友出错");
                    /************先不做失败处理 后续加*********/
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("私聊失败");
        }
    }

    /**
     * @Description: 群聊
     * @author xu_jiaHui
     * @date 2017/9/4 16:52
     */
    private void sendMsgToGroup(TextChatResultDto jsonDto) {
        System.out.println("进入群发方法");
        Set<String> clientIds = userSessionMap.keySet();
        WebSocketSession session = null;
        for (String userAccount : clientIds) {
            System.out.println("userAccount :" + userAccount);
            try {
                session = userSessionMap.get(userAccount);
                if (session != null && session.isOpen()) {
                    session.sendMessage(formatMsg(jsonDto));
                } else {
                    // chatService.sendMessage(jsonDto);//世界消息不保存记录
                    System.out.println(userAccount + " 用户已离线 群发消息保存");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * @Description: 绑定用户
     * @author xu_jiaHui
     * @date 2017/9/4 16:47
     */
    private void bindUserSession(TextChatResultDto jsonDto, WebSocketSession session) {
        sendNoticeToOnlineFriend(jsonDto);
        System.out.println("绑定用户：" + jsonDto.getUserAccount());
        userSessionMap.put(jsonDto.getUserAccount(), session);
        Set<String> list = userSessionMap.keySet();
        System.out.println("当前在线列表:" + list);
    }


    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        if (session.isOpen()) {
            session.close();
        }
        for (Iterator<Map.Entry<String, WebSocketSession>> entry = userSessionMap.entrySet().iterator(); entry.hasNext(); ) {
            Map.Entry<String, WebSocketSession> item = entry.next();
            if (item.getValue().equals(session)) {
                entry.remove();
                break;
            }
        }
    }

    /**
     * @Description: 断开连接后的操作
     * @author xu_jiaHui
     * @date 2017/8/31 18:11
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        TextChatResultDto jsonDto = new TextChatResultDto();
        for (Iterator<Map.Entry<String, WebSocketSession>> entry = userSessionMap.entrySet().iterator(); entry.hasNext(); ) {
            Map.Entry<String, WebSocketSession> item = entry.next();
            if (item.getValue().equals(session)) {
                try {
                    jsonDto.setUserAccount(item.getKey());
                    jsonDto.setType("logout");
                    chatService.updateLogoutTime(item.getKey());
                } catch (Exception e) {
                    System.out.println("记录失败");
                    e.printStackTrace();
                } finally {
                    System.out.println("我断开了连接:" + item.getKey());
                    sendNoticeToOnlineFriend(jsonDto);
                    entry.remove();
                }
                break;
            }
        }
        Set<String> list = userSessionMap.keySet();
        System.out.println("当前在线列表:" + list);
    }

    public TextMessage formatMsg(Object dto) {
        ObjectMapper om = new ObjectMapper();
        TextMessage message;
        try {
            message = new TextMessage(om.writeValueAsString(dto));
        } catch (Exception e) {
            message = new TextMessage("500");
        }
        return message;
    }

    /**
     * @Description: 给在线好友发送消息
     * @author xu_jiaHui
     * @date 2017/9/7 19:53
     */
    public void sendNoticeToOnlineFriend(TextChatResultDto jsonDto) {
        try {
            List<UserInfoDto> userInfoDtos = friendListService.getFriendListByUserAccount(jsonDto.getUserAccount());
            Set<String> onlineList = userSessionMap.keySet();
            for (String userAccount : onlineList) {
                for (UserInfoDto dto : userInfoDtos) {
                    if (userAccount.equals(dto.getUserAccount())) {
                        userSessionMap.get(userAccount).sendMessage(formatMsg(jsonDto));
                    }
                }
            }
        } catch (Exception e) {
            System.out.println("获取好友列表失败！ 在线提醒失败");
            e.printStackTrace();
        }
    }


}